/*******************************************************************************
 * Copyright (c) 2010, 2015 git@git.oschina.net:kaiwill/springstage.git
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 *******************************************************************************/
package com.qinyeit.serviceapp.service.system.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qinyeit.serviceapp.entity.Branch;
import com.qinyeit.serviceapp.entity.enums.RoleType;
import com.qinyeit.serviceapp.entity.enums.Scope;
import com.qinyeit.serviceapp.entity.system.ManagementAccount;
import com.qinyeit.serviceapp.entity.system.ManagementPermission;
import com.qinyeit.serviceapp.entity.system.ManagementRole;
import com.qinyeit.serviceapp.entity.system.MerchantRolePermission;
import com.qinyeit.serviceapp.exception.BusinessRunTimeException;
import com.qinyeit.serviceapp.exception.CanNotDeleteException;
import com.qinyeit.serviceapp.repository.system.ManagementPermissionRepository;
import com.qinyeit.serviceapp.repository.system.ManagementRoleRepository;
import com.qinyeit.serviceapp.service.organization.BranchService;
import com.qinyeit.serviceapp.service.system.ManagementPermissionService;
import com.qinyeit.serviceapp.service.system.ManagementRoleService;
import com.qinyeit.serviceapp.utils.SearchUtils;
import com.qinyetech.springstage.core.entity.search.Searchable;
import com.qinyetech.springstage.core.lang.QyMap;
import com.qinyetech.springstage.core.repository.jdbc.PageNamedParameterJdbcTemplate;
import com.qinyetech.springstage.core.service.BaseService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import javax.annotation.Resource;
import java.util.*;

/**
 * ClassName: SystemRoleServiceImpl <br/> 
 * Function: 角色 <br/>
 * date: 2015年10月6日 上午11:53:07 <br/> 
 *
 * @author wuqing
 * @version
 * @since JDK 1.7 
 */

@Service
public class ManagementRoleServiceImpl extends BaseService<ManagementRole, Long> implements ManagementRoleService {

    @Autowired
    private ManagementRoleRepository systemRoleRepository;
    @Autowired
    private ManagementPermissionRepository systemPermissionRepository;
    @Autowired
    private ManagementPermissionService managementPermissionService;
    @Autowired
    private PageNamedParameterJdbcTemplate jdbcTemplate;
    @Autowired
    private BranchService branchService;
    @Resource(name = "branchJdbcTemplate")
    private PageNamedParameterJdbcTemplate branchJdbcTemplate;


    @Override
    public boolean existsRepeat(BindingResult result, Long id, String name, String code) {
        if(StringUtils.isBlank(name)){
            result.rejectValue("name","name.empty","请填写角色名称");
            return true;
        }
        if(StringUtils.isBlank(code)){
            result.rejectValue("code","code.empty","请填写角色编码");
            return true;
        }

        Searchable searchable = null;
        ManagementRole systemRole = null;

        //验证name
        searchable = Searchable.newSearchable()
                .addSearchParam("id_ne", id)
                .addSearchParam("name_eq", name.trim());
        systemRole = super.findOne(searchable);
        if(systemRole!=null){
            result.rejectValue("name","name.exists","角色名称重复");
            return true;
        }

        //验证code
        searchable = Searchable.newSearchable()
                .addSearchParam("id_ne", id)
                .addSearchParam("code_eq", code.trim());
        systemRole = super.findOne(searchable);
        if(systemRole!=null){
            result.rejectValue("code","code.exists","角色编码重复");
            return true;
        }
        return false;
    }

    @Override
    public ManagementRole findByCode(String code) {
        return systemRoleRepository.findByCode(code);
    }

    /**
     * 角色更新权限
     * @param systemRoleId 角色主键
     * @param permissionIds 角色权限
     * @return 角色
     */
    @Transactional
    @Override
    public ManagementRole authorization(long systemRoleId, List<Long> permissionIds) {
        ManagementRole role = this.findById(systemRoleId);
        if(CollectionUtils.isNotEmpty(permissionIds)){
            List<ManagementPermission> permissionList = systemPermissionRepository.findAllById(permissionIds);
            role.setPermissions(new HashSet<>(permissionList));
        }else{
            role.setPermissions(new HashSet<>());
        }
        this.update(role);
        return role;
    }

    //更新子角色的权限
    @Transactional
    public void updateChildRole(ManagementRole role, List<ManagementRole> childs){
        List<ManagementPermission> tempList;
        for(ManagementRole roleItem : childs){
            tempList = new ArrayList<>();
            for(ManagementPermission permission : roleItem.getPermissions()){
                if(role.getPermissions().contains(permission)){
                    tempList.add(permission);
                }
            }
            if(tempList.size()>0){
                authorization(roleItem,tempList);
            }

        }
    }

    @Transactional
    public ManagementRole authorization(ManagementRole role, List<ManagementPermission> permissionList){
        role.setPermissions(new HashSet<>(permissionList));
        this.update(role);
        return role;
    }


    /**
     * 删除角色
     * @param id 角色主键
     * @throws CanNotDeleteException 如果角色下有账号的时候抛出异常
     */
    @Transactional
    @Override
    public void destroy(Long id) throws CanNotDeleteException {
        List<ManagementAccount> accounts = systemRoleRepository.findAccountByRoleId(id);
        if (CollectionUtils.isEmpty(accounts)) {
            //删除
            super.delete(id);
            return;
        }
        throw new CanNotDeleteException();
    }

    @Transactional
    @Override
    public void saveData(JSONObject data, Long merchantGroupId,String operator) {
        if (data==null){
            throw new BusinessRunTimeException("信息不能为空",10001);
        }
        Long id = data.getLong("id");
        ManagementRole managementRole = null;
        boolean isUpdate = false;
        if(id!=null){
            isUpdate = true;
            managementRole = this.findById(id);
            //删除权限串
            systemPermissionRepository.deletedRolePermissions(id);
            systemPermissionRepository.deletedRolebranchPermissions(id);
        }else {
            managementRole = new ManagementRole() ;
            managementRole.setCode("merchant_group_"+UUID.randomUUID().toString().replaceAll("-",""));
            managementRole.setMerchantGroupId(merchantGroupId);
        }
        managementRole.setType(RoleType.valueOf(data.getString("type")));
        managementRole.setName(data.getString("name"));
        managementRole.setOperatorName(operator);
        managementRole = this.update(managementRole);
        if (managementRole.getType()==RoleType.CHAINROLE){
            JSONArray ids = data.getJSONArray("permissions");
            Set<ManagementPermission> permissionSet = new HashSet<>();
            ManagementPermission permission = null;
            if(CollectionUtils.isNotEmpty(ids)){
                for (int i = 0; i < ids.size(); i++) {
                    if(ids.getLongValue(i)==0){
                        continue;
                    }
                    permission = managementPermissionService.findById(ids.getLong(i));
                    if(permission!=null){
                        permissionSet.add(permission);
                    }
                }
                managementRole.setPermissions(permissionSet);
            }else {
                managementRole.setPermissions(null);
            }
            managementRole = this.update(managementRole);
        }else if (managementRole.getType()==RoleType.BRANCHROLE){
            JSONArray ids = data.getJSONArray("branchBackPermissions");
            Map<String,?>[] params=null;
            QyMap param = null;
            String sql = "";
            if(CollectionUtils.isNotEmpty(ids)){
                params=new QyMap[ids.size()];
                for (int i = 0; i < ids.size(); i++) {
                    param = QyMap.map("merchantGroupId",merchantGroupId)
                            .setv("permissionId",ids.getLong(i))
                            .setv("roleId",managementRole.getId())
                            .setv("scope", Scope.BACK_END.getKey());
                    params[i] = param;
                }
                sql = "INSERT INTO merchant_role_permissions (create_at,is_deleted,status,merchant_group_id,permission_id,role_id,scope) " +
                        "values(now(),0,0,:merchantGroupId,:permissionId,:roleId,:scope) ";
                jdbcTemplate.batchUpdate(sql,params);
            }

            ids = data.getJSONArray("branchFrontPermissions");
            if(CollectionUtils.isNotEmpty(ids)){
                params=new QyMap[ids.size()];
                for (int i = 0; i < ids.size(); i++) {
                    param = QyMap.map("merchantGroupId",merchantGroupId)
                            .setv("permissionId",ids.getLong(i))
                            .setv("roleId",managementRole.getId())
                            .setv("scope", Scope.FRONT_ENT.getKey());
                    params[i] = param;
                }
                sql = "INSERT INTO merchant_role_permissions (create_at,is_deleted,status,merchant_group_id,permission_id,role_id,scope) " +
                        "values(now(),0,0,:merchantGroupId,:permissionId,:roleId,:scope) ";
                jdbcTemplate.batchUpdate(sql,params);
            }
        }
        //编辑 将门店对应的权限修改
        if (isUpdate){
            updatebranchPermissions(managementRole.getId(),merchantGroupId);
        }
    }

    /**
     * 修改角色 修改角色对应门店的权限
     * @param roleId
     * @param merchantGroupId
     */
    private void updatebranchPermissions(Long roleId,Long merchantGroupId) {
        Searchable searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchParam("templateId_eq",roleId);
        List<Branch> branchList = branchService.findWithSort(searchable);
        if (CollectionUtils.isNotEmpty(branchList)){
            for (Branch branch : branchList) {
                branchService.updateBranchPermissions(branch);
            }
        }
    }

    @Override
    public List<Object> getPermission(Long roleId) {
        if (roleId==null){
            return null;
        }
        String sql = "SELECT mrp.management_permission_id FROM management_role_permissions mrp \n" +
                "LEFT JOIN management_permissions mp ON mp.id = mrp.management_permission_id\n" +
                " WHERE mrp.management_role_id = :roleId AND mp.type = 'Button'";
        SqlParameterSource sqlParameterSource=new MapSqlParameterSource("roleId",roleId);
        List<Map<String,Object>> mapList = jdbcTemplate.queryForList(sql,sqlParameterSource);
        List<Object> permissions = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(mapList)){
            for (Map<String, Object> map : mapList) {
                permissions.add(map.get("management_permission_id"));
            }
        }

        return permissions;
    }

    @Override
    public List<Long> getBranchPermissions(Long roleId, Scope scope) {
        String sql = "SELECT permission_id from merchant_role_permissions where role_id = :roleId and scope=:scope and permission_id !=0";
        QyMap map = QyMap.map("roleId",roleId)
                .setv("scope",scope.getKey());
        List<Map<String,Object>> mapList = jdbcTemplate.queryForList(sql,map);

        List<Long> ids = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(mapList)){
            mapList.forEach(x->{
                ids.add(Long.valueOf(x.get("permission_id").toString()));
            });
        }
        return ids;
    }

    @Override
    public List<ManagementRole> getPositions(Long merchantGroupId){
        /*String sql = "SELECT * from management_roles where is_deleted = 0 and code != 'administrator' AND merchant_group_id = :merchantGroupId";
        Map<String,Object> params = Maps.newHashMap();
        params.put("merchantGroupId",merchantGroupId);
        List<Map<String,Object>> mapList = jdbcTemplate.queryForList(sql,params);*/

        Searchable searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchParam("type_eq",RoleType.CHAINROLE);
        searchable.addSearchParam("code_ne","administrator");
        List<ManagementRole> roleList = this.findWithSort(searchable);

        return roleList;
    }

    @Override
    public ManagementRole save(ManagementRole m) {
        return super.save(m);
    }

    @Override
    public ManagementRole saveAndFlush(ManagementRole m) {
        return super.saveAndFlush(m);
    }
}
